package com.github.hgkmail.hello.cmd;

import com.github.hgkmail.hello.cmd.helper.*;
import com.google.common.base.Joiner;
import com.thoughtworks.qdox.model.JavaClass;
import com.thoughtworks.qdox.model.JavaField;
import com.thoughtworks.qdox.model.JavaMethod;
import org.apache.velocity.VelocityContext;

import javax.print.Doc;

import java.util.List;
import java.util.stream.Collectors;

import static com.github.hgkmail.hello.cmd.helper.DocTagUtil.*;
import static java.lang.System.out;

/**
 * 生成DAO
 *
 * @author kimhuang
 * @date 2021/2/12
 */
public class GenDataAccessObject extends BaseParseClass {

    public static void main(String[] args) {
        new GenDataAccessObject().run();
    }

    @Override
    public void run() {
        parseClass(new RenderDataAccessObject());
    }

    private class RenderDataAccessObject implements ParseClassListener {
        private DaoInfo dao = new DaoInfo();
        private EntityInfo entity = new EntityInfo();

        RenderDataAccessObject() {
        }

        @Override
        public void onStart(JavaClass jClass) {
            dao.setName(jClass.getSimpleName()+"Dao");
            dao.setAuthor(firstTagValue(jClass, "author", ""));
            dao.setDate(firstTagValue(jClass, "date", ""));
            dao.setComment(firstTagValue(jClass, "comment", ""));
            dao.setRepoAnnotation(ParseClassConfig.DAO_IDIOM_REPOSITORY);
            dao.setCriteriaName(jClass.getSimpleName()+"Criteria");
            dao.setCriteriaVarName(toLowerCaseFirstOne(dao.getCriteriaName()));
            dao.setProviderName(jClass.getSimpleName()+"SqlProvider");

            entity.setName(jClass.getSimpleName());
            entity.setVarName(toLowerCaseFirstOne(jClass.getSimpleName()));
            entity.setListName(entity.getVarName()+"List");
            entity.setTable(DocTagUtil.firstTagValue(jClass, "table", ""));
        }

        @Override
        public void onField(JavaClass jClass, JavaField jField) {
            EntityInfo e = entity;
            e.getAllFields().add(jField.getName());

            // dbTrigger表示数据库自动更新的字段，比如更新时间字段
            if (jField.getTagByName("primary")==null && jField.getTagByName("dbTrigger")==null) {
                e.getManualFields().add(jField.getName());
            }

            // 主键字段
            if (jField.getTagByName("primary")!=null) {
                e.setPrimaryField(jField.getName());
                e.setPrimaryFieldU(toUpperCaseFirstOne(jField.getName()));
                e.setPrimaryType(jField.getType().getSimpleName());
                e.setPrimaryList(jField.getName()+"List");
                e.setPrimaryColumn(firstTagValue(jField, "column", jField.getName()));
                if (jField.getTagByName("useGenKey")!=null) {
                    e.setUseGenKey(true);
                }
            }
        }

        @Override
        public void onMethod(JavaClass jClass, JavaMethod jMethod) {
            //nothing
        }

        @Override
        public void onEnd(JavaClass jClass) {
            EntityInfo e = entity;
            e.setAllFieldsPart(Joiner.on(COMMA).skipNulls().join(e.getAllFields()));
            e.setManualFieldsPart(Joiner.on(COMMA).skipNulls().join(e.getManualFields()));

            List<String> fieldsWithBracket = e.getManualFields().stream().map(f-> String.format("#{%s}", f)).collect(Collectors.toList());
            e.setManualFieldsBracketPart(Joiner.on(COMMA).skipNulls().join(fieldsWithBracket));

            List<String> fieldsWithParam = e.getManualFields().stream().map(f-> String.format("#{%s.%s}", e.getVarName(), f)).collect(Collectors.toList());
            e.setManualFieldsParamPart(Joiner.on(COMMA).skipNulls().join(fieldsWithParam));

            renderVm("code-maker/generate/simple_dao_java.vm", new RenderListener() {
                @Override
                public void beforeRender(VelocityContext vContext) {
                    vContext.put("dao", dao);
                    vContext.put("entity", entity);
                }

                @Override
                public void afterRender(VelocityContext vContext, String result) {
                    out.println(result);
                }
            });
        }

    }

}
